<?php

namespace addons\formdesign\library;

use addons\formdesign\library\helper\HtmlDomParser;
use think\Db;

class Formdesign
{

    /**
     * PHP 解析表单
     * @param type $template 表单设计器里的Html内容
     * @param type $fields 字段总数
     * @return string
     */
    public function parse_form($template, $fields = 0)
    {
        $template_data = $add_fields = array();
        $html = HtmlDomParser::str_get_html($template);
        foreach ($html->find("div.form-group div.options input[type='hidden']") as $plugins) {
            //遍历所有控件
            $preg = '/data-(\w*)=\"([^\"\']*)\"/u';
            preg_match_all($preg, $plugins->html(), $temparr);
            $params = array_combine($temparr[1], $temparr[2]);
            //如果是新的控件
            if (strpos($params['name'], 'NewField') !== false) {
                $fields++;
                $name = $params['name'] = 'data_' . $fields;
                if (in_array($params['type'], ['checkboxs', 'select', 'selects', 'radios', 'selectpicker', 'selectpickers'])) {
                    $params['name'] = 'data_' . $fields . '[]';
                }
            }
            $name = str_replace(['[', ']'], '', $params['name']);
            $plugins->setAttribute('data-name', $params['name']);
            $add_fields[$name] = array(
                'name' => $name,
                'type' => $params['type'],
                'comment' => $params['title'],
            );
            $template_data[$name] = $params;
        }
        $templateHtml = $html->save();
        $html->clear();
        $parse_form = array(
            'fields' => $fields,
            'template' => $templateHtml,
            'data' => $template_data,
            'add_fields' => $add_fields,
        );
        return $parse_form;
    }

    /**
     * 获取控件字段类型 的sql
     * @param type $plugins
     * @return type
     */
    public function field_type_sql($plugins)
    {
        if ($plugins['type'] == 'textarea' or $plugins['type'] == 'listctrl') {
            return 'text COMMENT \'' . $plugins['comment'] . '\'';
        } else {
            return 'varchar(255) NOT NULL DEFAULT \'\' COMMENT \'' . $plugins['comment'] . '\'';
        }
    }

    /**
     * 返回表名
     * @param type $tname
     * @return type
     */
    public function tname($tname)
    {
        $tname = strtolower($tname);
        return config('database.prefix') . $tname;
    }

    /**
     * 创建数据表， 通过fields自动计算字段增长
     * 表中存取数据利用 foreign_id 进行
     * @param type $formid
     * @param type $add_fields
     * @return boolean
     */
    public function parse_table($formid, $add_fields)
    {
        $tname = self::tname("formdesign_form_data_" . $formid);
        $exist = Db::query("show tables like '" . $tname . "'");
        if (!$exist) {
            $fields = '';
            foreach ($add_fields as $value) {
                $fields .= '`' . $value['name'] . '` ' . self::field_type_sql($value) . ',';
            }
            $sql = "CREATE TABLE `" . $tname . "` (
              `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
              `uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '标识',
              `foreign_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '表单ID',
              `about_dataid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '相关数据表',
              " . $fields . "
              `status` varchar(30) NOT NULL DEFAULT 'normal' COMMENT '状态',
              `createtime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
              `updatetime` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
              PRIMARY KEY (`id`),
              KEY `uid` (`uid`),
              KEY `foreign_id` (`foreign_id`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8;";
            $create = db()->execute($sql);
            if ($create !== false) {
                $create = true;
            }
            return $create;
        } else {
            $fields = Db::getTableInfo($tname, 'fields');
            $dot = '';
            $sql = "ALTER TABLE `" . $tname . "` ";
            foreach ($add_fields as $value) {
                if (!in_array($value['name'], $fields)) {
                    $sql .= $dot . "ADD COLUMN `" . $value['name'] . "` " . self::field_type_sql($value);
                    $dot = ',';
                }
            }
            $sql .= ';';
            if ($dot != '') {
                $create = db()->execute($sql);
                if ($create !== false) {
                    $create = true;
                }

                return $create;
            }
        }
        return true;
    }

    /**
     * 编译表单
     * @param array $form 表单数据
     * @param array $form_data 表单值
     * @param string $controller 编译类型
     * @return string HTMl字符串
     */
    public function unparse_form($form, $form_data = [], $controller)
    {
        $html = '';
        switch ($controller) {
            case 'preview': //预览
                $html = self::buildFormGroup($form);
                break;
            case 'design': //设计
                $html = self::buildFormGroup($form);
                break;
            case 'add': //添加数据
                $html = self::buildFormGroup($form);
                break;
            case 'edit': //编辑
                $html = self::buildFormGroup($form, $form_data);
                break;
            case 'view': //查询显示
                $html = self::buildFormGroup($form, $form_data);
                break;
            default:
                $html = self::buildFormGroup($form);
                break;
        }
        return $html;
    }

    /**
     * 处理查询显示，下个版本实现
     * @param type $form
     * @param type $form_data
     */
    public function unparse_plaintext($form, $form_data)
    {
        $form_plugins = unserialize($form['content_data']);
        //根据控件生成纯文本的显示。
    }

    /**
     * 宏控件处理函数
     * @param type $data
     * @param type $def_value
     * @param type $controller
     * @return type
     */
    public function macros_parse($data, $def_value = '', $controller = array())
    {
        $tpl = $data['content'];
        $date_format = '';
        switch ($data['orgtype']) {
            case 'sys_date':
                $date_format = 'Y-m-d';
                break;
            case 'sys_date_cn':
                $date_format = 'Y年n月j日';
                break;
            case 'sys_date_cn_short3':
                $date_format = 'Y年';
                break;
            case 'sys_date_cn_short4':
                $date_format = 'Y';
                break;
            case 'sys_date_cn_short1':
                $date_format = 'Y年m月';
                break;
            case 'sys_date_cn_short2':
                $date_format = 'm月d日';
                break;
            case 'sys_time':
                $date_format = 'H:i:s';
                break;
            case 'sys_datetime':
                $date_format = 'Y-m-d H:i:s';
                break;
            case 'sys_week': //周
                if (!$def_value) {
                    $dateArray = getdate($date);
                    $wday = $dateArray["wday"];
                    $week = array("日", "一", "二", "三", "四", "五", "六");
                    $def_value = '星期' . $week[$wday];
                }
                $tpl = str_replace('{macros}', $def_value, $tpl);
                break;
            case 'sys_userid':
                if (!$def_value) {
                    $def_value = $controller['user']['uid'];
                }

                $tpl = str_replace('{macros}', $def_value, $tpl);
                break;
            case 'sys_realname':
                if (!$def_value) {
                    $def_value = $controller['user']['real_name'];
                }

                $tpl = str_replace('{macros}', $def_value, $tpl);
                break;
            default:
                $tpl = str_replace('{macros}', '未完善的宏控件', $tpl);
                break;
        }
        //时间
        if ($date_format) {
            $def_value = str_replace('年', '-', $def_value);
            $def_value = str_replace('月', '-', $def_value);
            $def_value = str_replace('日', '', $def_value);
            $def_value = trim($def_value, '-');

            $timestamp = 0;
            if ($def_value) {
                if (strlen($def_value) == 4) {
                    $def_value .= '-01';
                }
                $timestamp = strtotime($def_value);
            } else {
                $timestamp = time();
            }

            if (!$timestamp) {
                $tpl = str_replace('{macros}', $def_value, $tpl); //时间转换失败时
            } else {
                $tpl = str_replace('{macros}', date($date_format, $timestamp), $tpl);
            }
        }

        return $tpl;
    }

    /**
     * 抽出表单提交后 控件的值
     * @param array $form 表单数据
     * @param array $post_data 表单值
     * @return array
     */
    public function unparse_data($form, $post_data)
    {
        $tpl_data = array_keys(unserialize($form['content_data']));
        foreach ($post_data as $key => $value) {
            if (!in_array($key, $tpl_data)) {
                unset($post_data[$key]);
            } else {
                if (is_array($value)) {
                    if (count($value) == count($value, 1)) {
                        $post_data[$key] = implode(',', $value);
                    } else {
                        foreach ($value as $v)
                        {
                            $v = join(",",$v); //可以用implode将一维数组转换为用逗号连接的字符串
                            $temp[] = $v;
                        }
                        $value="";
                        foreach($temp as $v){
                            $value.="".$v."".",";
                        }
                        $value=substr($value,0,-1);
                        $post_data[$key] = $value;
                    }
                }
            }
        };
        return $post_data;
    }

    /**
     * 生成控件Form-Group
     * @param array $form 表单数据
     * @param array $form_data 表单值
     * @return string HTMl字符串
     */
    public function buildFormGroup($form, $form_data = [])
    {
        $html = HtmlDomParser::str_get_html($form['content']);
        foreach ($html->find("div.form-group") as &$formgroup) {
            $form_type = $formgroup->getAttribute('data-type');
            if ($form_type !== "" && $form_type && $form_type !== 'html') {
                $plugins = $formgroup->find("div.options input[type='hidden']", 0);
                if ($plugins) {
                    $preg = '/data-(\w*)=\"([^\"\']*)\"/u';
                    preg_match_all($preg, $plugins->html(), $temparr);
                    $params = array_combine($temparr[1], $temparr[2]);
                  
                    if (!empty($params)) {
                        if (!empty($form_data)) {
                            $form_data = self::unparse_data($form, $form_data);
                           
                            $isMatched = preg_match('/data_[0-9]*/', $params['name'], $matches);
                            foreach ($form_data as $name => $value) {
                               
                                //if ($isMatched && $matches[0] === $name) {
                                    if ($params['name'] === $name|| $isMatched && $matches[0] === $name) {
                                    $params['value'] = $value;
                                    if (in_array($params['type'], ['checkboxs', 'select', 'selects', 'radios', 'selectpicker', 'selectpickers'])) {
                                        $params['value'] = explode(',', $value);
                                    }
                                }
                            }
                        }
                        $tpl = self::buildPlugins($params);
                        $tpl = str_replace(array("\r\n", "\r", "\n"), "", $tpl);
                        //重新生成form-group
                        $dom_label = $formgroup->find('label.plugins-label', 0);
                        $dom_plugins = $formgroup->find('div.plugins', 0);
                        $dom_option = $formgroup->find('div.options', 0);
                        $dom_plugins->innertext = '<div>' . $tpl . '</div>'; //不知道为什么不加空格不现实Switcher中的a标签
                        $formgroup->outertext = '<div class="form-group" data-type="' . $form_type . '">'
                        . $dom_label->html() . $dom_plugins->html() . $dom_option->html() . '</div>';
                    }
                }
            }
        }
        return $html->html();
    }

    /**
     * 生成控件
     * @param array $params 控件参数
     * @return string 控件HTML字符串
     */
    public function buildPlugins($params)
    {
        $params['value'] = isset($params['value']) ? $params['value'] : '';
        $params['list'] = isset($params['list']) ? $params['list'] : '';
        $params['options'] = isset($params['options']) ? $params['options'] : [];
        $params['options']['data-rule'] = '';
        if(in_array($params['type'],['upload','uploads','image','images'])){
            $params['inputAttr']= [];
            $params['uploadAttr']= [];
            $params['previewAttr']= [];
            $params['chooseAttr']= [];
        }
        //匹配 参数
        foreach ($params as $key => $value) {
            $isMatched = preg_match('/^options_(\w.*)/', $key, $matches);
            if ($isMatched) {
                if ($matches[1] == 'rule') {
                    $params['options']['data-rule'] .= $value ? $value : '';
                } else if ($matches[1] == 'rule_range') {
                    $params['options']['data-rule'] .= $value ? ';range(' . $value . '~)' : '';
                } else if ($matches[1] == 'rule_length') {
                    $params['options']['data-rule'] .= $value ? ';length(' . $value . ')' : '';   
                } else if($matches[1] == 'inputattr'){
                    $params['inputAttr'] = $value ==='false'? false:[];
                } else if($matches[1] == 'uploadattr'){
                    $params['uploadAttr'] = $value ==='false'?false:[];
                } else if($matches[1] == 'chooseattr'){
                    $params['chooseAttr'] = $value ==='false'?false:[];
                } else if($matches[1] == 'previewattr'){
                    $params['previewAttr'] = $value ==='false'?false:[];
                }
                 else {
                    $matches[1] = str_replace('_', '-', $matches[1]);
                    $params['options'][$matches[1]] = $value;
                }
                if ($matches[1] == 'readonly') {
                    if ($params['options'][$matches[1]] !== 'true') {
                        unset($params['options'][$matches[1]]);
                    }
                }
            }
            if (in_array($params['type'], ['checkboxs', 'select', 'selects', 'radios', 'selectpicker', 'selectpickers'])) {
                if ($key == 'list') {
                    if (!is_array($params['list'])) {
                        if (self::is_json($params['list'])) {
                            $params['list'] = htmlspecialchars_decode($params['list']);
                            $params['list'] = json_decode($params['list'], true);
                        } else {
                            $params['list'] = ['0' => '选项一', '1' => '选项二'];
                        }
                    }
                }
            }
        }
        $build = new \fast\FormBuilder();
        $plugins = '';
        try {
            switch (trim($params['type'])) {
                case 'label':
                    //Label标签
                    $plugins = $build->label($params['name'], $params['value'], []);
                    break;
                case 'input':
                    //按类型生成文本框
                    $plugins = $build->input($params['text_type'], $params['name'], $params['value'], $params['options']);
                    break;
                case 'text':
                    //普通文本框
                    $plugins = $build->text($params['name'], $params['value'], $params['options']);
                    break;
                case 'password':
                    //密码文本框
                    $plugins = $build->password($params['name'], $params['options']);
                    break;
                case 'hidden':
                    //隐藏文本框
                    $plugins = $build->hidden($params['name'], $params['value'], $params['options']);
                    break;
                case 'email':
                    //Email文本框
                    $plugins = $build->email($params['name'], $params['value'], $params['options']);
                    break;
                case 'url':
                    //URL文本框
                    $plugins = $build->url($params['name'], $params['value'], $params['options']);
                    break;
                case 'file':
                    //文件组件
                    $plugins = $build->file($params['name'], $params['options']);
                    break;
                case 'textarea':
                    //多行文本框
                    $plugins = $build->textarea($params['name'], $params['value'], $params['options']);
                    break;
                case 'editor':
                    //富文本编辑器
                    $plugins = $build->editor($params['name'], $params['value'], $params['options']);
                    break;
                case 'select':
                    //下拉列表组件
                    $plugins = $build->select($params['name'], $params['list'], $params['value'], $params['options']);
                    break;
                case 'selects':
                    //下拉列表组件(多选)
                    $plugins = $build->selects($params['name'], $params['list'], $params['value'], $params['options']);
                    break;
                case 'selectpicker':
                    //下拉列表组件(友好)
                    $plugins = $build->selectpicker($params['name'], $params['list'], $params['value'], $params['options']);
                    break;
                case 'selectpickers':
                    //下拉列表组件(友好)(多选)
                    $plugins = $build->selectpickers($params['name'], $params['list'], $params['value'], $params['options']);
                    break;
                case 'selectpage':
                    //动态下拉列表组件
                    $plugins = $build->selectpage($params['name'], $params['value'], $params['url'], $params['field'], $params['primarykey'], $params['options']);
                    break;
                case 'selectpages':
                    //动态下拉列表组件(多选)
                    $plugins = $build->selectpages($params['name'], $params['value'], $params['url'], $params['field'], $params['primarykey'], $params['options']);
                    break;
                case 'slider':
                    //滑块组件
                    $plugins = $build->slider($params['name'], $params['min'], $params['max'], $params['step'], $params['value'], $params['options']);
                    break;
                case 'citypicker':
                    //城市选择组件
                    $plugins = $build->citypicker($params['name'], $params['value'], $params['options']);
                    break;
                case 'switcher':
                    //开关组件
                    $plugins = $build->switcher($params['name'], $params['value'], $params['options']);
                    break;
                case 'datepicker':
                    //日期选择组件
                    $plugins = $build->datepicker($params['name'], $params['value'], $params['options']);
                    break;
                case 'timepicker':
                    //时间选择组件
                    $plugins = $build->timepicker($params['name'], $params['value'], $params['options']);
                    break;
                case 'datetimepicker':
                    //日期时间选择组件
                    $plugins = $build->datetimepicker($params['name'], $params['value'], $params['options']);
                    break;
                case 'daterange':
                    //日期区间组件
                    $plugins = $build->daterange($params['name'], $params['value'], $params['options']);
                    break;
                case 'timerange':
                    //时间区间组件
                    $plugins = $build->timerange($params['name'], $params['value'], $params['options']);
                    break;
                case 'datetimerange':
                    //日期时间区间组件
                    $plugins = $build->datetimerange($params['name'], $params['value'], $params['options']);
                    break;
                case 'fieldlist':
                    //字段列表组件
                    $plugins = $build->fieldlist($params['name'], $params['value'], null, $params['template'], $params['options']);
                    break;
                case 'cxselect':
                    //联动组件
                    $plugins = $build->cxselect($params['url'], ['province', 'city'], ['province' => 37, 'city' => 38], $params['options']);
                    break;
                case 'selectRange':
                    //选择数字区间
                    $plugins = $build->selectRange($params['name'], $params['begin'], $params['end'], $params['value'], $params['options']);
                    break;
                case 'selectYear':
                    //选择年
                    $plugins = $build->selectYear($params['name'], $params['begin'], $params['end'], $params['value'], $params['options']);
                    break;
                case 'selectMonth':
                    //选择月
                    $plugins = $build->selectMonth($params['name'], $params['value'], $params['options'], $params['format']);
                    break;
                case 'checkbox':
                    //单个复选框
                    $plugins = $build->checkbox($params['name'], $params['value'] = '1', $checked = null, $params['options']);
                    break;
                case 'checkboxs':
                    //一组复选框
                    $plugins = $build->checkboxs($params['name'], $params['list'], $params['value'], $params['options']);
                    break;
                case 'radio':
                    //单个单选框
                    $plugins = $build->radio($params['name'], $params['value'], $checked = null, $params['options']);
                    break;
                case 'radios':
                    //一组单选框
                    $plugins = $build->radios($params['name'], $params['list'], $params['value'], $params['options']);
                    break;
                case 'image':
                    //上传图片组件
                    $plugins = $build->image($params['name'], $params['value'], $params['inputAttr'], $params['uploadAttr'], $params['chooseAttr'], $params['previewAttr']);
                    break;
                case 'images':
                    //上传图片组件(多图)）
                    $plugins = $build->images($params['name'], $params['value'], $params['inputAttr'], $params['uploadAttr'], $params['chooseAttr'], $params['previewAttr']);
                    break;
                case 'upload':
                    //上传文件组件
                    $plugins = $build->upload($params['name'], $params['value'], $params['inputAttr'], $params['uploadAttr'], $params['chooseAttr'], $params['previewAttr']);
                    break;
                case 'uploads':
                    //上传文件组件(多文件)）
                    $plugins = $build->uploads($params['name'], $params['value'], $params['inputAttr'], $params['uploadAttr'], $params['chooseAttr'], $params['previewAttr']);
                    break;
                case 'button':
                    //表单button
                    $plugins = $build->button($params['value'], $params['options']);
                    break;
            }
            return $plugins;
        } catch (Exception $e) {
            print_r($e->getMessage());
        }
    }

    /**
     * 判断是否为JSON数据
     * @param string $str 字符串
     * @return bool
     */
    public function is_json($str)
    {
        $json_str = str_replace('\\', '', $str);
        $out_arr = array();
        preg_match('/{.*}/', $json_str, $out_arr);
        if (!empty($out_arr)) {
            return true;
        } else {
            return false;
        }
    }

}
